local pb = require "pb"
local protoc = require "protoc".new()
local protocol = require "proto.protocol"

local lfs = require "lfs"
require "utils.file"

local sep = string.match(package.config, "[^\n]+")

-------------------------------------------------------------------------------
local function _encode_packet(name, data)
    local id = protocol[name]
    local buf = pb.encode(name, data)
    return string.pack(">Hc" .. #buf, id, buf)
end

local function _decode_packet(bytes)
    local size = #bytes - 2
    local id, buf = string.unpack(">Hc" .. tostring(size), bytes)
    local name = protocol[id]
    local data = pb.decode(name, buf)
    return name, data
end

-------------------------------------------------------------------------------
PROTOCOL_D = {}

function PROTOCOL_D:init(path)
    return protoc:loadfile(path)
end

function PROTOCOL_D:encode(name, data)
    local ok, bytes = pcall(_encode_packet, name, data)
    if not ok then
        print(string.format("encode_packet: parse command error, name = %s", name))
        return
    end
    return ok, bytes
end

function PROTOCOL_D:decode(bytes)
    local ok, name, data = pcall(_decode_packet, bytes)
    if not ok then
        print(string.format("decode_packet: parse command error, buf = %s", pb.tohex(bytes)))
        return
    end
    return ok, name, data
end

PROTOCOL_D:init("./proto/tanker.proto")
PROTOCOL_D:init("./proto/tunnel.proto")

function PROTOCOL_D:make_protocol()
    local root = lfs.currentdir()
    local path = root .. sep .. "proto"

    --local result = {}
    local content = "\n"
    for _, filepath in ipairs(attrdir(path)) do
        repeat
            -- print(filepath)
            local ext = getextension(filepath)
            if "proto" ~= ext then -- 读取proto结尾的文件
                break
            end
            local f = io.open(filepath, "r")
            if not f then
                break
            end
            io.input(f)
            local line = io.read()
            local num
            local message
            local package_str

            while line do
                 print("line: ",line)
                if not package_str then -- 先读取package
                    package_str = string.match(line, "%s*package%s+(%w+)%s*;%s*$")
                else -- package已经读取到
                    if not num then -- 没有id 先查找数字id
                         print("num: ", num)
                        num = string.match(line, ".+{%s*id:%s*(%d+)%s*}%s*$")
                        print("num2: ", num)
                    else -- 有id,取message
                        message = string.match(line, "%s*message%s*(%w*)%s*{%s*$")
                        print("message: ", message)
                        if message then -- 有message
                             print("id: ",num, " message: ",message)
                            -- result[tonumber(num)] = message
                            content = content .. string.format('protocol[%s] = "%s.%s" \n', num, package_str, message) --保存的内容
                            num = nil
                            message = nil
                        end
                    end
                end

                line = io.read()
            end
            -- local content = f:read("*all")
            io.close(f)
        until true
    end

    --for k,v in pairs(result) do
    --content = content .. string.format("protocol[%s] = \"%s\" \n", k,v)
    --end

    local first =
        [[

----------------------------------------------------------
----- 此文件为自动生成,执行方法 PROTOCOL_D:make_protocol() --
----------------------------------------------------------

local protocol = {}
]]
    local last =
        [[

local ret = {}
for k, v in pairs(protocol) do
    ret[k] = v
    ret[v] = k
end
return ret
]]
    -- print(content .. last)
    local outfile = path .. sep .. "protocol.lua"
    local o = io.open(outfile, "w")
    if not o then
        printf("open %s error", outfile)
        return false
    end
    io.output(o)
    io.write(first .. content .. last)
    io.close(o)
    printf("make %s success", outfile)
    return true
end
